package com.mall.pay.wxpay.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum;
import com.ijpay.wxpay.model.v3.*;

import com.mall.business.controller.TConfigController;
import com.mall.business.domain.*;
import com.mall.business.enums.OrderStatus;
import com.mall.business.service.*;
import com.mall.common.core.controller.BaseController;
import com.mall.common.core.domain.AjaxResult;
import com.mall.common.core.domain.entity.SysUser;
import com.mall.common.exception.ServiceException;
import com.mall.common.utils.SecurityUtils;
import com.mall.common.utils.StringUtils;
import com.mall.pay.utils.SignatureVerifier;
import com.mall.pay.wxpay.config.WxPayV3Bean;
import com.mall.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;


/**
 * 微信支付
 */
@Controller
@RequestMapping("/v3")
public class WxPayV3Controller  {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private final static int OK = 200;

    @Resource
    WxPayV3Bean wxPayV3Bean;

    String serialNo;
    String platSerialNo;

    @Autowired
    private ITOrderService tOrderService;


    @Autowired
    private ITOrderItemService orderItemService;

    @Autowired
    private ITSocreService socreService;

    @Autowired
    private ITConfigService tConfigService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ITOrderRefundService orderRefundService;






//
//	@Autowired
//	private PayService payService;

    private String getSerialNumber() {
        if (StrUtil.isEmpty(serialNo)) {
            // 获取证书序列号
            X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());
            if (null != certificate) {
                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
                // 提前两天检查证书是否有效
                boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Bean.getMchId(), -2);
                log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
            }
        }
        System.out.println("serialNo:" + serialNo);
        return serialNo;
    }


    /**
     * 支付
     */
    @RequestMapping("/jsApiPay")
    @ResponseBody
    public AjaxResult jsApiPay(@RequestBody PayParam vo) {
        try {
            TOrder order = tOrderService.getOrderByOrderNo(vo.getOrderNo());
            SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
            if(sysUser==null){
                throw new ServiceException("用户不存在");
            }
            String openId = sysUser.getOpenId();
            if(StringUtils.isEmpty(openId)){
                throw new ServiceException("用户未绑定微信");
            }
            String outTradeNo = order.getOrderNo() + "_" + IdUtil.simpleUUID().substring(0, 10);
            // 支付方式
            order.setPayType("1");
            tOrderService.updateById(order);
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(wxPayV3Bean.getAppId())
                    .setMchid(wxPayV3Bean.getMchId())
                    .setDescription("支付")
                    .setOut_trade_no(outTradeNo)
                    .setTime_expire(timeExpire)
                    .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX")
                    .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify"))
                    .setAmount(new Amount().setTotal(order.getTotalPrice().multiply(new BigDecimal(100)).intValue()))
                    .setPayer(new Payer().setOpenid(openId));

            log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.JS_API_PAY.toString(),
                    wxPayV3Bean.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Bean.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );
            log.info("统一下单响应 {}", response);
            // 根据证书序列号查询对应的证书来验证签名结果
            //应答时间戳
            String timestamp = response.getHeader("Wechatpay-Timestamp");
            //应答随机串\n
            String nonceStr = response.getHeader("Wechatpay-Nonce");
            String signature = response.getHeader("Wechatpay-Signature");
            String bodyre = response.getBody();
            boolean verifySignature = verifySignature(timestamp,nonceStr,bodyre,signature);
            log.info("verifySignature: {}", verifySignature);
            if (response.getStatus() == OK && verifySignature) {
                String body = response.getBody();
                JSONObject jsonObject = JSONUtil.parseObj(body);
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.jsApiCreateSign(wxPayV3Bean.getAppId(), prepayId, wxPayV3Bean.getKeyPath());
                log.info("唤起支付参数:{}", map);
                return  AjaxResult.success(JSONUtil.toJsonStr(map)) ;
            }
            return AjaxResult.success(response);
        } catch (Exception e) {
            log.error("系统异常", e);
            return  AjaxResult.error(e.getMessage());
        }
    }



    /**
     * 积分支付(支付成功)
     */
    @PostMapping("/scorePay")
    @ResponseBody
    public AjaxResult scorePay(@Validated @RequestBody PayParam vo) {
        TOrder order = tOrderService.getOrderByOrderNo(vo.getOrderNo());
        // 支付方式 积分支付
        order.setPayType(vo.getPayType());
        order.setOrderStatus(OrderStatus.PADYED.value());
        order.setFinallyTime(DateUtil.date());
        order.setPayTime(DateUtil.date());
        order.setIsPayed("1");

        if("2".equals(vo.getPayType())){
            // 扣除积分
            BigDecimal useIntegral = order.getUseIntegral();
            // useIntegral 的负数
            BigDecimal totalScore = socreService.getTotalScore();
            if(totalScore.compareTo(useIntegral)<0){
                return AjaxResult.error("积分不足");
            }
            TSocre socre = new TSocre();
            socre.setUserId(order.getUserId());
            socre.setScore(order.getUseIntegral().negate());
            socre.setSrType("1");
            // 扣除积分
            socre.setRemark("订单号："+order.getOrderNo()+" 扣除积分");
            socreService.save(socre);
            order.setRemark("积分支付");
        }else if("4".equals(vo.getPayType())){
            order.setRemark("抽奖支付");
        }else if("5".equals(vo.getPayType())){
            order.setRemark("优惠券支付");
            String couponId = order.getCouponId();
            if(StringUtils.isNotEmpty(couponId)){
                TCouponUser couponUser = new TCouponUser();
                couponUser.setCouponId(couponId);
                couponUser.setUserId(order.getUserId());
                List<TCouponUser> tCouponUsers = tCouponUserService.selectTCouponUserList(couponUser);
                for (TCouponUser tCouponUser : tCouponUsers) {
                    // 使用时间
                    tCouponUser.setUseTime(DateUtil.date());
                    tCouponUser.setStatus("1");
                    tCouponUserService.updateById(tCouponUser);
                }
            }
        }
        tOrderService.updateById(order);

        return  AjaxResult.success();
    }


    /**
     * 银行支付申请
     */
    @PostMapping("/bankSqPay")
    @ResponseBody
    public AjaxResult bankSqPay(@Validated  @RequestBody BankPaySqParam vo) {
        TOrder order = tOrderService.getOrderByOrderNo(vo.getOrderNo());
        if(!"1".equals(order.getOrderStatus())){
            return AjaxResult.error("订单状态异常");
        }
        // 3对公打款
        order.setPayType("3");
        order.setCheckStatus("1");
        order.setCommitDate(DateUtil.date());
//        order.setBankInfo(vo.getBankInfo());
        order.setBankPayImage(vo.getBankPayImage());
        tOrderService.updateById(order);
        return  AjaxResult.success();
    }

    /**
     * 银行支付申请
     */
    @PostMapping("/bankSqCheckPay")
    @ResponseBody
    public AjaxResult bankSqCheckPay(  @RequestBody TOrder vo)  {
        TOrder order = tOrderService.getById(vo.getId());
//        if(!"1".equals(order.getOrderStatus())){
//           return AjaxResult.error("订单状态异常");
//        }

        String checkStatus = vo.getCheckStatus();
        order.setCheckStatus(checkStatus);
        if("2".equals(checkStatus)){
            this.processOrder(order.getOrderNo(),vo.getCheckRemark(),vo.getCheckStatus());
        }else{
            order.setCheckRemark(vo.getCheckRemark());
            order.setCheckDate(DateUtil.date());
            tOrderService.updateById(order);
        }


        return  AjaxResult.success();
    }

   /**
   *
   * 获取平台证书
   *
   *
   */
    @RequestMapping("/get")
    @ResponseBody
    public String v3Get() {
        // 获取平台证书列表

        // 检查商户证书是否有效
        X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());
        if (certificate == null) {
            throw new ServiceException("商户证书路径无效，请检查配置");
        }
        boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Bean.getMchId(), -2);
        if (!isValid) {
            throw new ServiceException("商户证书已过期，请更新证书");
        }
        try {
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.ALL.getCode()),
                    wxPayV3Bean.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Bean.getKeyPath(),
                    "",
                    AuthTypeEnum.RSA.getCode()
            );
            Map<String, List<String>> headers = response.getHeaders();
            log.info("请求头: {}", headers);
            String timestamp = response.getHeader("Wechatpay-Timestamp");
            String nonceStr = response.getHeader("Wechatpay-Nonce");
            String serialNumber = response.getHeader("Wechatpay-Serial");
            String signature = response.getHeader("Wechatpay-Signature");

            String body = response.getBody();
            int status = response.getStatus();

            log.info("serialNumber: {}", serialNumber);
            log.info("status: {}", status);
            log.info("body: {}", body);
            int isOk = 200;
            if (status == isOk) {
                JSONObject jsonObject = JSONUtil.parseObj(body);
                JSONArray dataArray = jsonObject.getJSONArray("data");
                // 默认认为只有一个平台证书
                JSONObject encryptObject = dataArray.getJSONObject(0);
                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
                String associatedData = encryptCertificate.getStr("associated_data");
                String cipherText = encryptCertificate.getStr("ciphertext");
                String nonce = encryptCertificate.getStr("nonce");
                String algorithm = encryptCertificate.getStr("algorithm");
                String serialNo = encryptObject.getStr("serial_no");
                final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayV3Bean.getPlatformCertPath());
                log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
                // 根据证书序列号查询对应的证书来验证签名结果
                boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
                log.info("verifySignature:{}", verifySignature);
            }
            return body;
        } catch (Exception e) {
            log.error("获取平台证书列表异常", e);
            return null;
        }
    }


    private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) {
        try {
            String key3 = wxPayV3Bean.getApiKey3();
            String publicKey;
            if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
                publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
            } else {
                AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8));
                // 平台证书密文解密
                // encrypt_certificate 中的  associated_data nonce  ciphertext
                publicKey = aesUtil.decryptToString(
                        associatedData.getBytes(StandardCharsets.UTF_8),
                        nonce.getBytes(StandardCharsets.UTF_8),
                        cipherText
                );
            }
            if (StrUtil.isNotEmpty(publicKey)) {
                // 保存证书
                FileWriter writer = new FileWriter(certPath);
                writer.write(publicKey);
                // 获取平台证书序列号
                X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
                return certificate.getSerialNumber().toString(16).toUpperCase();
            }
            return "";
        } catch (Exception e) {
            log.error("保存平台证书异常", e);
            return e.getMessage();
        }
    }





    @RequestMapping(value = "/payNotify", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})
    @ResponseBody
    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> map = new HashMap<>(12);
        try {
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String signature = request.getHeader("Wechatpay-Signature");

            log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
            // 2. 获取请求体（加密的通知数据）
            String result = HttpKit.readData(request);
            log.info("支付通知密文: {}", result);
            boolean verifySignature = verifySignature(timestamp,nonce,result,signature);
            log.info("verifySignature:{}", verifySignature);
            String  kk="";
            if (verifySignature) {
                JSONObject resultObject = JSONUtil.parseObj(result);
                JSONObject resource = resultObject.getJSONObject("resource");
                String cipherText = resource.getStr("ciphertext");
                String nonceStr = resource.getStr("nonce");
                String associatedData = resource.getStr("associated_data");
                AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8));
                kk= aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonceStr.getBytes(StandardCharsets.UTF_8), cipherText);
            } else {
                throw new Exception("签名错误");
            }
            log.info("支付通知明文 {}", kk);
            Gson gson = new Gson();
            if (StrUtil.isNotEmpty(kk)) {
                HashMap hashMap = gson.fromJson(kk, HashMap.class);
                String orderNo = (String) hashMap.get("out_trade_no");
                System.out.println(orderNo);
                // orderNo 是这种格式的    String outTradeNo = order.getOrderNo() + "_" + IdUtil.simpleUUID();
                // 根据orderNo 获取真实的orderNo
                String orderNo_real = orderNo.split("_")[0];
                this.processOrder(orderNo_real,"","");
                System.out.println("微信notify_url 验证成功开始处理业务");
                response.setStatus(200);
                map.put("code", "SUCCESS");
                map.put("message", "SUCCESS");
            } else {
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "签名错误");
            }
            response.setHeader("Content-type", ContentType.JSON.toString());
            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
            response.flushBuffer();
        } catch (Exception e) {
            log.error("系统异常", e);
        }
    }

    public   static boolean verifySignature(String timestamp, String nonceStr, String body, String signature) {
        try {

            // 加载公钥 (假设已经通过证书序列号获取到公钥)
            String publicKeyStr = "-----BEGIN PUBLIC KEY-----\n" +
                    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1udWYPWSD2P3QBi8BZV\n" +
                    "DRvtPPEZccm+LpSEDuJCrWSZGvdnHnRhTu7RmSzcYpKvGQjJKkJbLDdGnDKZSe58\n" +
                    "CuTZRd4jPWZBt3zBsvOFIahMuBuv+EbEcZuDb5XbjIoYCnIUz3ZF04wo+pCYXS2+\n" +
                    "tSQ/DR4x6NxziUJ+nBM9AZq/vzAAg7wy4BNodbOLJwWpKHNpZlTsXHM+ZHRwv3sF\n" +
                    "l8+bNTO7McF24s5B1AsDGJnSSd9q8D8bBS+vyyOA1Y6A06Qm0P9A7qNsH8CjuV2O\n" +
                    "SKQqomddd3Owt+PcCzcHMSHopqejM8fLYsWY+4pDLn9TwRNsNykP3AW/LuDjltzD\n" +
                    "QQIDAQAB\n" +
                    "-----END PUBLIC KEY-----"; // 公钥内容

            // 去掉 BEGIN/END PUBLIC KEY 和换行符，只保留 Base64 部分
            publicKeyStr = publicKeyStr
                    .replace("-----BEGIN PUBLIC KEY-----", "")
                    .replace("-----END PUBLIC KEY-----", "")
                    .replaceAll("\\s+", ""); // 移除所有空白字符（包括换行）

            // 将公钥字符串转换为 PublicKey 对象
            PublicKey publicKey = KeyFactory.getInstance("RSA")
                    .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr)));
            // 1. 构造验签字符串
            String signStr = timestamp + "\n"
                    + nonceStr + "\n"
                    + body + "\n";

            // 2. 初始化 Signature 对象
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(publicKey);

            // 3. 更新验签字符串
            sign.update(signStr.getBytes(StandardCharsets.UTF_8));

            // 4. 验证签名
            return sign.verify(Base64.getDecoder().decode(signature));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }








    @Autowired
    private ITCouponUserService tCouponUserService;


    @Autowired
    private ITWalletService walletService;
    public void processOrder(String orderNo,String checkRemark,String checkStatus) {
        log.info("处理订单");
        //解密报文
//        String plainText = decryptFromResource(bodyMap);
        //将明文转换成map
//        Gson gson = new Gson();
//        HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
        /*在对业务数据进行状态检查和处理之前，
        要采用数据锁进行并发控制，
        以避免函数重入造成的数据混乱*/
        //尝试获取锁：
        // 成功获取则立即返回true，获取失败则立即返回false。不必一直等待锁的释放
        String uuId = IdUtil.simpleUUID();
        //处理重复的通知
        //接口调用的幂等性：无论接口被调用多少次，产生的结果是一致的。
        String orderStatus = this.getOrderStatus(orderNo);
        if (!OrderStatus.UNPAY.value().equals(orderStatus)) {
            return;
        }
        log.info("更新订单状态-----------开始");
        //更新订单状态
        TOrder tOrder = tOrderService.getOrderByOrderNo(orderNo);
        tOrder.setOrderStatus(OrderStatus.PADYED.value());
        tOrder.setFinallyTime(DateUtil.date());
        tOrder.setPayTime(DateUtil.date());
        tOrder.setIsPayed("1");
        if(!StringUtils.isEmpty(checkStatus)){
            tOrder.setCheckStatus(checkStatus);
            tOrder.setCheckRemark(checkRemark);
            tOrder.setCheckDate(DateUtil.date());
        }
        tOrderService.updateById(tOrder);
        BigDecimal totalPrice = tOrder.getPayPrice();
        String ordermoney_per = tConfigService.getConfigValue("ordermoney_per");
        if(!StringUtils.isEmpty(ordermoney_per)  &&  totalPrice.compareTo(BigDecimal.ZERO)>0){
            BigDecimal score = totalPrice.multiply(new BigDecimal(ordermoney_per));
            long scoreAsLong = score.longValue();
            log.info("更新订单状态-----送积分------");
            if(scoreAsLong>0){
                // 支付成功  送积分
                TSocre  socre = new TSocre();
                socre.setUserId(tOrder.getUserId());
                socre.setScore(totalPrice.multiply(new BigDecimal(ordermoney_per)));
                socre.setSrType("4");
                socre.setRemark("订单号："+orderNo+" 送积分");
                socreService.save(socre);
                log.info("更新订单状态-----送积分成功------");
            }
        }
        // 邀请用户返现
        walletService.saveDxMoney(tOrder.getUserId(), totalPrice);
        log.info("更新订单状态-----------成功");
    }





    /**
     * 根据订单号获取订单状态
     *
     * @param orderNo
     * @return
     */
    public String getOrderStatus(String orderNo) {
        TOrder orderInfo = new TOrder();
        orderInfo.setOrderNo(orderNo);
        List<TOrder> tOrderInfos = tOrderService.selectTOrderList(orderInfo);
        if (CollectionUtils.isEmpty(tOrderInfos)) {
            return null;
        } else {
            return tOrderInfos.get(0).getOrderStatus();

        }


    }

//    private TOrder getNoPayOrderByUserId(String userId, String productId) {
//        TOrder info = new TOrder();
//        info.setOrderStatus(OrderStatus.NOTPAY.getType());
//        info.setUserId(userId);
//        info.setProductId(productId);
//        List<TOrder> tOrderInfos = tOrderService.selectTOrderList(info);
//        if (CollectionUtils.isEmpty(tOrderInfos)) {
//            return null;
//        } else {
//            return tOrderInfos.get(0);
//        }
//
//    }


    /**
     * @param outTradeNo
     * @Author:zhaoyongke
     * @Description:前端 定时查询 关闭二维码
     * @Date: 2024/2/7 14:10
     */
    @RequestMapping("/query")
    @ResponseBody
    public String query(@RequestParam String outTradeNo) {
        try {
            Map<String, String> params = new HashMap<>(16);
            params.put("mchid", wxPayV3Bean.getMchId());

            log.info("统一下单参数 {}", JSONUtil.toJsonStr(params));
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    String.format(BasePayApiEnum.ORDER_QUERY_BY_OUT_TRADE_NO.toString(), outTradeNo),
                    wxPayV3Bean.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Bean.getKeyPath(),
                    params,
                    AuthTypeEnum.RSA.getCode()
            );
            log.info("查询响应 {}", response);
            if (response.getStatus() == OK) {
                // 根据证书序列号查询对应的证书来验证签名结果
                boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
                log.info("verifySignature: {}", verifySignature);
                return response.getBody();
            }
            return JSONUtil.toJsonStr(response);
        } catch (Exception e) {
            log.error("系统异常", e);
            return e.getMessage();
        }
    }

    /**
     *
     *
     *退款
     *
     */
    @RequestMapping("/refund")
    @ResponseBody
    public AjaxResult refund(@RequestParam(required = false) String transactionId,
                         @RequestParam(required = false) String outTradeNo,@RequestParam(required = false) String refoudId) {
        try {
            String outRefundNo = PayKit.generateStr();
            log.info("商户退款单号: {}", outRefundNo);
            TOrderRefund orderRefund = orderRefundService.selectTOrderRefundById(refoudId);
            if(!"1".equals(orderRefund.getPayType())){
                return AjaxResult.error("只能微信退款");
            }
            String orderItemId = orderRefund.getOrderItemId();
            TOrderItem orderItem = orderItemService.selectTOrderItemByOrderItemId(orderItemId);
            String productId = orderItem.getProductId();
            String productName = orderItem.getProductName();
            tOrderService.getOrderByOrderNo(outTradeNo);
            BigDecimal productPrice = orderRefund.getProductPrice();
            //转成 int
            int refundAmount = productPrice.multiply(new BigDecimal(100)).intValue();

            Long refundNum = orderRefund.getRefundNum();
            // 转成 数量
            int refundAmountInt = refundNum.intValue();
            List<RefundGoodsDetail> list = new ArrayList<>();
            RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail()
                    .setMerchant_goods_id(productId)
                    .setGoods_name(productName)
                    .setUnit_price(refundAmount)
                    .setRefund_amount(refundAmount)
                    .setRefund_quantity(refundAmountInt);
            list.add(refundGoodsDetail);

            RefundModel refundModel = new RefundModel()
                    .setOut_refund_no(outRefundNo)
                    .setReason("IJPay 测试退款")
                    .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/refundNotify"))
                    .setAmount(new RefundAmount().setRefund(refundAmount).setTotal(refundAmount).setCurrency("CNY"))
                    .setGoods_detail(list);

            if (StrUtil.isNotEmpty(transactionId)) {
                refundModel.setTransaction_id(transactionId);
            }
            if (StrUtil.isNotEmpty(outTradeNo)) {
                refundModel.setOut_trade_no(outTradeNo);
            }
            log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel));
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.REFUND.toString(),
                    wxPayV3Bean.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Bean.getKeyPath(),
                    JSONUtil.toJsonStr(refundModel)
            );

            String timestamp = response.getHeader("Wechatpay-Timestamp");
            String nonceStr = response.getHeader("Wechatpay-Nonce");
            String signature = response.getHeader("Wechatpay-Signature");
            String result = response.getBody();
            boolean verifySignature = verifySignature(timestamp,nonceStr,result,signature);
            log.info("verifySignature: {}", verifySignature);
            log.info("退款响应 {}", response);
            if (verifySignature) {
                orderRefund.setReturnStatus("2");
                orderRefundService.updateById(orderRefund);
                String body = response.getBody();
                return  AjaxResult.success(body);
                // {
                //    "code": "INVALID_REQUEST",
                //    "message": "订单已全额退款"
                //} 解析 更新状态


            }
        } catch (Exception e) {
            log.error("系统异常", e);
            return  AjaxResult.error(e.getMessage());
        }
        return null;
    }








//    public static void main(String[] args) {
//        try {
//            // 读取公钥文件
//            String publicKeyPath = "D:\\cert\\mall\\pub_key.pem";
//            String publicKeyContent = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(publicKeyPath)));
//            publicKeyContent = publicKeyContent.replace("-----BEGIN PUBLIC KEY-----", "")
//                    .replace("-----END PUBLIC KEY-----", "")
//                    .replaceAll("\\s", "");
//
//            // 解析公钥
//            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyContent));
//            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//            PublicKey publicKey = keyFactory.generatePublic(keySpec);
//
//            // 将公钥转换为Base64字符串
//            String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
//            System.out.println("Public Key Base64: " + publicKeyBase64);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//    }
    public static void main(String[] args) throws Exception {
        String timestamp = "1698745600"; // 应答时间戳
        String nonceStr = "abcdefg1234567"; // 应答随机串
        String body = "{\"code\":\"SUCCESS\",\"message\":\"成功\"}"; // 响应体
        String signature = "your-signature-here"; // 微信支付签名



    }





}
